package org.annotationz;

import com.alibaba.fastjson2.JSONObject;
import org.annotationz.util.UpperCaseWithUnderscoreUtils;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@SupportedAnnotationTypes("org.annotationz.MyData") // 只处理这个注解；
public class MyDataProcesser extends AbstractProcessor {

    // 整个类的模版
    private final static String model = """
            package @packageName;
            public class @ClassName {
                String s = "@value";
                @fields
            }
            """;
    // 单行字符串的模版
    private final static String fieldModel = "public static String @field;";

    private Messager messager;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        // Element操作类，用来处理Element的工具
        messager = processingEnv.getMessager();
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        // 设置为能够支持最新版本
        return SourceVersion.latestSupported();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        // print("process 处理 annotations = " + annotations);
        for (TypeElement annotation : annotations) {
            Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
            // print("annotatedElements = " + annotatedElements);
            for (Element annotatedElement : annotatedElements) {
                if (annotatedElement instanceof TypeElement typeElement) {
                    try {
                        rewriteCoder(typeElement, roundEnv);
                    } catch (Exception e) {
                        print("异常--->" + e.getCause() + e.getMessage());
                    }
                } else {
                    throw new RuntimeException("该注解只能用在类上");
                }
            }


        }

        return false;
    }

    void print(Object info) {
        messager.printMessage(Diagnostic.Kind.WARNING, JSONObject.toJSONString(info));
    }

    // 重写代码
    private void rewriteCoder(TypeElement annotation, RoundEnvironment roundEnv) throws IOException {
        final String packageClassName = annotation.getQualifiedName().toString();
        final String clazzName = annotation.getSimpleName().toString();

        MyData annotation1 = annotation.getAnnotation(MyData.class);
        print(annotation1.value());

        // 所有属性的集合
        List<VariableElement> fieldList = new ArrayList<>();
        List<? extends Element> enclosedElements = annotation.getEnclosedElements();
        for (Element enclosedElement : enclosedElements) {
            if (enclosedElement instanceof VariableElement variableElement) {
                // print(variableElement.getSimpleName());
                // print("头部是否有注解 = " + variableElement.getAnnotation(Deprecated.class));
                fieldList.add(variableElement);
            }
        }

        //
        List<String> fieldNameList = fieldList.stream().map(VariableElement::getSimpleName).map(Objects::toString).collect(Collectors.toList());
        // print(fieldNameList);

        // 开始写入类
        String classContent = model;
        classContent = classContent.replace("@packageName", packageClassName.substring(0, packageClassName.lastIndexOf(".")));
        final String endClassName = clazzName + "Def";
        classContent = classContent.replace("@ClassName", endClassName);

        // 写入所有字段
        String fields = "";
        for (String fieldName : fieldNameList) {
            fields += fieldModel.replace("@field", UpperCaseWithUnderscoreUtils.toUpperCaseWithUnderscore(fieldName)) + "\n";
        }
        classContent = classContent.replace("@fields", fields);


        // print(classContent);

        JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(endClassName);
        PrintWriter out = new PrintWriter(builderFile.openWriter());
        out.println(classContent);

        out.close();
    }


}
